package com.mentalhealthplatform.global.rbac.service.entity;

import com.mentalhealthplatform.global.rbac.dto.normal.RoleDTO;
import com.mentalhealthplatform.exception.role.RoleNotFoundException;
import com.mentalhealthplatform.global.rbac.model.Menu;
import com.mentalhealthplatform.global.rbac.model.Permission;
import com.mentalhealthplatform.global.rbac.model.Role;
import com.mentalhealthplatform.global.rbac.repository.MenuRepository;
import com.mentalhealthplatform.global.rbac.repository.PermissionRepository;
import com.mentalhealthplatform.global.rbac.repository.RoleRepository;
import com.mentalhealthplatform.utils.PagedResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

@Service
public class RoleService {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    @Autowired
    private MenuRepository menuRepository;

    // 获取角色列表，支持分页和排序
    public PagedResponse<RoleDTO> getRoles(String displayName, int page, int size, String sortField, String sortOrder) {

        // 默认排序：如果没有传入排序字段，则使用 id 降序
        Sort sort = Sort.by(Sort.Order.asc("orderNum"));

        // 如果传入了排序字段和排序顺序
        if (sortField != null && !sortField.isEmpty()) {
            // 根据传入的排序顺序（ASC 或 DESC）构建排序对象
            Sort.Order order = "ASC".equalsIgnoreCase(sortOrder)
                    ? Sort.Order.asc(sortField)
                    : Sort.Order.desc(sortField);

            // 合并默认排序和传入的排序条件
            sort = Sort.by(order);
        }

        // 创建分页请求对象
        Pageable pageable = PageRequest.of(page, size, sort);

        // 调用 Repository 方法查询并返回分页数据
        Page<Role> pageResult;
        if (displayName != null && !displayName.isEmpty()) {
            // 如果有 roleName 过滤条件，则进行模糊查询
            pageResult = roleRepository.findByDisplayName(displayName, pageable);
        } else {
            // 否则查询所有角色
            pageResult = roleRepository.findAll(pageable);
        }

        // 使用 PagedResponse 封装分页数据
        List<RoleDTO> roleDTOs = pageResult.getContent().stream()
                .map(RoleDTO::convertToDTO)
                .collect(Collectors.toList());


        return new PagedResponse<>(roleDTOs, pageResult.getNumber(), pageResult.getSize(),
                pageResult.getTotalElements(), pageResult.getTotalPages(), pageResult.isLast());
    }




    public void deleteRole(Long id) {
        Role role = roleRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("Role with ID " + id + " not found"));

        roleRepository.deleteById(id);
    }

    public Role createRole(RoleDTO roleDTO) {
        Optional<Role> existingRole = roleRepository.findByIdentifier(roleDTO.getIdentifier());

        if (existingRole.isPresent()) {
            // 如果角色已存在，抛出异常或返回错误信息
            throw new IllegalArgumentException("角色已存在: " + roleDTO.getIdentifier());
        }

        // 如果角色不存在，创建并保存新的角色
        Role role = new Role();
        role.setIdentifier(roleDTO.getIdentifier());
        role.setDisplayName(roleDTO.getDisplayName());
        role.setOrderNum(roleDTO.getOrderNum());
        role.setStatus(roleDTO.isStatus());

        return roleRepository.save(role);

    }

    // 更新角色基本信息
    public Role updateRole(Long roleId, RoleDTO roleDTO) {
        // 查找角色
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        // 更新角色的基本信息
        role.setDisplayName(roleDTO.getDisplayName());
        role.setIdentifier(roleDTO.getIdentifier());
        role.setOrderNum(roleDTO.getOrderNum());
        role.setStatus(roleDTO.isStatus());

        // 保存更新后的角色
        return roleRepository.save(role);
    }

    public void assignMenusToRole(Long roleId, List<Long> menuIds) {
        // 查找角色
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        // 从数据库中找到所有的菜单 ID
        List<Menu> newMenus = menuRepository.findAllById(menuIds);

        // 获取角色当前已有的菜单
        Set<Menu> existingMenus = role.getMenus();

        // 将新的菜单追加到现有的菜单集合中
        existingMenus.addAll(newMenus);

        // 保存角色与菜单的关系
        roleRepository.save(role);
    }

    public void assignPermissionsToRole(Long roleId, List<Long> permissionIds) {
        // 查找角色
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        // 从数据库中找到所有的权限 ID
        List<Permission> newPermissions = permissionRepository.findAllById(permissionIds);

        // 获取角色当前已有的权限
        Set<Permission> existingPermissions = role.getPermissions();

        // 将新的权限追加到现有的权限集合中
        existingPermissions.addAll(newPermissions);

        // 保存角色与权限的关系
        roleRepository.save(role);
    }

    public void removeMenusFromRole(Long roleId, List<Long> menuIds) {
        // 查找角色
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        // 从数据库中找到需要撤回的菜单
        List<Menu> menusToRemove = menuRepository.findAllById(menuIds);

        // 获取角色当前已有的菜单
        Set<Menu> existingMenus = role.getMenus();

        // 从现有菜单集合中移除指定的菜单
        existingMenus.removeAll(menusToRemove);

        // 保存角色与菜单的关系
        roleRepository.save(role);
    }

    public void removePermissionsFromRole(Long roleId, List<Long> permissionIds) {
        // 查找角色
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        // 从数据库中找到需要撤回的权限
        List<Permission> permissionsToRemove = permissionRepository.findAllById(permissionIds);

        // 获取角色当前已有的权限
        Set<Permission> existingPermissions = role.getPermissions();

        // 从现有权限集合中移除指定的权限
        existingPermissions.removeAll(permissionsToRemove);

        // 保存角色与权限的关系
        roleRepository.save(role);
    }

    // 获取角色的菜单 ID 列表
    public List<Long> getMenuIdsByRoleId(Long roleId) {
        return roleRepository.findById(roleId)
                .map(role -> role.getMenus().stream().map(Menu::getId).collect(Collectors.toList()))
                .orElseThrow(() -> new RuntimeException("角色未找到"));
    }

    // 获取角色的权限 ID 列表
    public List<Long> getPermissionIdsByRoleId(Long roleId) {
        return roleRepository.findById(roleId)
                .map(role -> role.getPermissions().stream().map(Permission::getId).collect(Collectors.toList()))
                .orElseThrow(() -> new RuntimeException("角色未找到"));
    }

    public void deleteRoleById(Long roleId) {
        if (!roleRepository.existsById(roleId)) {
            throw new RoleNotFoundException("角色不存在");
        }
        roleRepository.deleteById(roleId);
    }

    public void updateRoleStatus(Long roleId, boolean newStatus) {
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new IllegalArgumentException("角色未找到: " + roleId));

        role.setStatus(newStatus);

        roleRepository.save(role);
    }

    public List<RoleDTO> getRolesForExport(String status) {
        // 如果状态为空，获取所有角色
        List<Role> roles;
        if (status != null) {
            boolean isStatus = Boolean.parseBoolean(status);
            roles = roleRepository.findByStatus(isStatus);
        } else {
            roles = roleRepository.findAll();
        }

        // 将角色实体转换为 RoleDTO
        return roles.stream()
                .map(RoleDTO::convertToDTO)
                .collect(Collectors.toList());
    }

    public List<RoleDTO> getRolesByIds(List<Long> roleIds) {
        // 根据 roleIds 查询数据库获取对应的角色信息
        return roleRepository.findAllById(roleIds).stream()
                .map(role -> new RoleDTO(role))
                .collect(Collectors.toList());
    }

    public List<RoleDTO> getAllRoles() {

        return roleRepository.findAll().stream()
                .map(role -> new RoleDTO(role))
                .collect(Collectors.toList());
    }
}
